<?php

/*
 * 心愿相关
 * @auth bzyy
 * 2015年8月26日18:18:24
 */

class PostalModel extends BaseModel
{
    const TYPE_FREE = 1;
    const RULE_TYPE_DEFAULT = 2;//包邮类型
    /**
     * 微信端的调用方法，参考
     * $freight_model = S()->getHerxiFreightService();
     * $freight_model->addinfo($address_info['region_id']);
     * $f = $freight_model->addgoods($good['goods_id'],$good['buy_num']);
     * $template_list = $freight_model->expresslist();
     * 如果想用该实例计算第二个店铺，清空一下，数据
     * $freight_model->cleargoods();
     */

    public $error = '';//默认规则
    protected $addinfo = array();//地区信息

    protected $_rulesinfo = array();

    protected $_model;

    protected $_table_postal_template;
    protected $_table_post_rule_region;
    protected $_table_post_express;
    protected $_table_post_exp_rule;
    protected $_table_goods;
    protected $_table_region;


    public function __construct($params, $db)
    {
        parent::__construct($params, $db);

        $this->_model = $this;
        $this->_table_post_exp_rule = DB_PREFIX . 'post_exp_rule';
        $this->_table_post_rule_region = DB_PREFIX . 'post_rule_region';
        $this->_table_post_express = DB_PREFIX . 'post_express';
        $this->_table_postal_template = DB_PREFIX . 'postal_template';
        $this->_table_goods = DB_PREFIX . 'goods';
        $this->_table_region = DB_PREFIX . 'region';
    }

    /**
     * 把要计算运费的商品一个一个的添加进来，
     * 对于商品是否有效，是否在售等其他信息在方法外面判断，
     * 当前类只专注计算，不对合法性做处理。
     *
     * @param $goods_id
     * @param $goodsNumber
     * @param string $expressName ：快递名称
     * @return bool
     */
    public function addgoods($goods_id, $goodsNumber, $expressName = '')
    {
        $goods = $this->goodsinfo($goods_id);

        //检测是否为空
        if (!isset($this->_rulesinfo[$goods['post_template_id']]['rules'])) {
            $rules = $this->findrules($goods['post_template_id'], $expressName);

            if (empty($rules)) {
                return false;
            }
            $this->_rulesinfo[$goods['post_template_id']]['rules'] = $rules;

        }

        $goods['number'] = $goodsNumber;
        $this->_rulesinfo[$goods['post_template_id']]['goods'][] = $goods;
        return true;

    }

    /**
     * @param $goods_id
     * @return array
     * 取得商品信息
     * 不对商品的库存等信息进行验证，那些有效性的验证应该在加入本类之前处理。
     */
    protected function goodsinfo($goods_id)
    {
        $sql = "select * from {$this->_table_goods} where goods_id='{$goods_id}'";

        $goodsinfo = $this->_model->getRow($sql);

        return $goodsinfo;
    }

    /**
     * @param $template_id
     * @return array
     *
     * 根据运费模板id 获取对应的规则信息，已规则名称作为对应的key值进行返回
     *
     * 有对应的收货地址才可以进行规则的查找
     */
    protected function findrules($template_id, $expressname = '')
    {
        if (empty($this->addinfo)) {
            $this->error = '请设置有效的地区';
            return false;
        }

        $addon_where = '';

        if ($expressname) {
            $addon_where .= " and name='{$expressname}' ";
        }
        $sql = "select * from {$this->_table_post_express} where postal_id='{$template_id}' {$addon_where}";
        $express = (array)$this->_model->getAll($sql);
        if (empty($express)) {
            //$this->error = '快递方式不存在';
            //返回默认包邮快递
            $rules = array();
            $rules[] = array('first_price' => 0, 'express_id' => 0, 'ctype' => self::TYPE_FREE);
            return $rules;
        }
        $express_ids = array();
        foreach ($express as $val) {
            $express_ids[] = $val['id'];
        }

        //根据地区来找到规则

        $addr_condition = "reg.country='{$this->addinfo['country']}' and reg.province='{$this->addinfo['province']}' and reg.city='{$this->addinfo['city']}' and reg.region='{$this->addinfo['region']}' ";

        $addr_condition = " and (rul.ctype=" . self::RULE_TYPE_DEFAULT . " or ({$addr_condition}) )";

//        $sql = "select reg.*
//        from {$this->_table_post_rule_region} as reg left join {$this->_table_post_exp_rule} as rul on reg.rule_id=rul.id
//        where reg.express_id in (". implode(',',$express_ids) .") {$addr_condition} ";


        $sql = "select rul.*
        from {$this->_table_post_exp_rule} as rul left join {$this->_table_post_rule_region} as reg on rul.id = reg.rule_id
        where rul.express_id in (" . implode(',', $express_ids) . ") {$addr_condition}
        ";

        $region_info = (array)$this->_model->getAll($sql);

        $rules = array();
        foreach ($region_info as $val) {
            if (isset($rules[$val['express_id']])) {

                if ($val['ctype'] == self::RULE_TYPE_DEFAULT) {
                    continue;
                }
            }

            $rules[$val['express_id']] = $val;
        }


        return $rules;
    }

    /**
     * 清除商品信息
     *
     * 当生成多个订单的时候可用用的，
     * 比如A商家的订单生成后，不用再new一个对象，调用本方法就清空以前的信息了。
     * 然后可用在一次的添加上去。
     *
     */
    public function cleargoods()
    {
        $this->_rulesinfo = array();
    }

    /**
     * @return array|bool
     *
     * 添加完对应的商品，就可以调用本方法来取得对应的运费列表
     *
     *
     */
    public function expresslist()
    {
        //加测规则信息
        if (empty($this->_rulesinfo)) {
            $this->error = '商品数据为空';
            return false;
        }

        //找到相同快递的信息规则
        $expressnames = $this->uniqidexpress();
        if (empty($expressnames)) {
            return false;
        }

        $expresslist = array();
        foreach ($this->_rulesinfo as $info) {
            //变量规则，并填充数据
            foreach ($info['rules'] as $rule) {
                $name = $this->expressname($rule['express_id']);
                if (!in_array($name, $expressnames)) {
                    continue;
                }

                if (!isset($expresslist[$name])) {
                    $expresslist[$name] = 0;
                }

                $value = $this->goodsvalue($info['goods']);
                if ($value === false) {
                    return false;
                }
                $money = $this->makeprice($rule, $value);
                if ($money === false) {
                    return false;
                }

                $expresslist[$name] += $money;
            }
        }

        if (empty($expresslist)) {
            $this->error = '系统内部错误，没有相同的快递，无法合并选择';
            return false;
        }

        //数据排序
        if (count($expresslist) > 1) {
            asort($expresslist);
        }

        return $expresslist;
    }

    /**
     * 找到通用快递
     * 返回快递的名称
     *
     * 将快递方式在多个商品中进行合并筛选，找出共有的快递方式，以便用户选择。
     *
     */
    protected function uniqidexpress()
    {
        $express = array();
        foreach ($this->_rulesinfo as $val) {
            $tempname = array();
            foreach ($val['rules'] as $rule) {
                $name = $this->expressname($rule['express_id']);
                if (empty($name)) {
                    $this->error = '系统内部错误，获取快递名称时出错';
                    return false;
                }

                $tempname[] = $name;
            }
            $express[] = $tempname;
        }

        if (empty($express)) {
            $this->error = '系统内部错误，未找到快递数据';
            return false;
        }

        if (count($express) == 1) {
            return array_pop($express);
        }

        //找到数组的共同点

        $xname = call_user_func_array('array_intersect', $express);
        if (empty($xname)) {
            $this->error = '系统内部错误，快递方式不存在交集，无法统一快递方式';
            return false;
        }
        return $xname;


    }

    /**
     * @param $express_id
     * @return string
     *
     * 根据快递的编号找到快递的名称。
     * 取得快递的名称
     *
     */
    protected function expressname($express_id)
    {
        static $expressname = array(0 => '默认快递');
        if (isset($expressname[$express_id])) {
            return $expressname[$express_id];
        }

        $sql = "select * from " . $this->_table_post_express . " where id='{$express_id}' ";
        $express = $this->_model->getRow($sql);
        if ($express) {
            $expressname[$express_id] = $express['name'];
            return $express['name'];
        } else {
            $this->error = '系统内容错误,未找到对应的快递。';
            return false;
        }


    }

    /**
     * @param $goodsinfos
     * @return int
     *
     * 返回商品的参数统计总值,考虑到商品的数量
     *
     */
    protected function goodsvalue($goodsinfos)
    {
        $value = 0;
        foreach ($goodsinfos as $val) {
            $value += abs($val['number'] * $val['post_template_value']);
        }
        return $value;
    }

    /**
     * @param $ruleinfo 规则信息
     * @param $value    数值信息
     * @return int
     *
     * 根据规则计算价格
     *
     *
     */
    public function makeprice($ruleinfo, $value)
    {
        if ($ruleinfo['ctype'] == self::TYPE_FREE) {
            return 0;
        }

        if ($ruleinfo['first_price'] <= 0) {
            return 0;
        }

        if ($value <= $ruleinfo['first_value']) {
            return $ruleinfo['first_price'];
        }
        //超出首重
        $more = $value - $ruleinfo['first_value'];
        $moremoney = $ruleinfo['step_price'] * ceil($more / $ruleinfo['step']);

        $money = $moremoney + $ruleinfo['first_price'];

        $money = round($money, 2);
        return $money;
    }

    /**
     * 根据地区id 算地区信息
     * @param $region_id
     * @return bool
     * @author jyx
     * @date 2015/09/24
     */
    public function addinfo($region_id)
    {
        $adds = array();
        do {
            $sql = "select * from " . $this->_table_region . " where region_id='{$region_id}' ";
            $addinfo = $this->_model->getRow($sql);
            $adds[] = $region_id;
            $region_id = $addinfo['parent_id'];
        } while (!empty ($addinfo));
//        for ($i = 0; $i < 5; $i++) {
//            $sql = "select * from " . $this->_table_region . " where region_id='{$region_id}' ";
//            $addinfo = $this->_model->getRow($sql);
//
//            if (empty($addinfo)) {
//                break;
//            }
//            $adds[] = $region_id;
//            $region_id = $addinfo['parent_id'];
//        }

//        $sql = "select * from ".$this->_table_region." where parent_id='{$old_region_id}' ";
//        $info = $this->_model->getRow($sql);

        if (empty($adds)) {
            $this->error = "地址不完整";
            return false;
        }

        $adds = array_reverse($adds);

        list($country, $province, $city, $region) = $adds;
        $country = intval($country);
        $province = intval($province);
        $city = intval($city);
        $region = intval($region);

        //中国地质
        if ($country == 2) {
            if (empty($province)) {
                $this->error = "地址无效";
                return false;
            }
            $city = 0;
            $region = 0;
        }

        $this->addinfo = array('country' => $country, 'province' => $province, 'city' => $city, 'region' => $region);
        return true;
    }


}